package org.devf.fork.imsimulator.http;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.URLUtil;
import org.devf.fork.imsimulator.model.HttpConstant;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * DefaultHttpClient related
 *
 * @author wanghuafu
 * @since 1.0  2023/9/12 17:41
 */
public class DefaultHttpClient implements ApiClient {

    protected Map<String, String> headerMap = new HashMap<>();
    private List<HttpListener> httpListenerList;

    public String get(String url ,Map<String,Object> params){
       String urlParams =  URLUtil.buildQuery(params, Charset.defaultCharset());
        return execute(url+"?"+urlParams,HttpConstant.ReqMethod.GET,null);
    }


    @Override
    public String execute(String url, String method, Object body) {
        if (!url.startsWith("/")) {
            url = "/" + url;
        }
        HttpURLConnection connection = null;
        DataOutputStream wr = null;
        int responseCode = 0;
        try {
            // 打开 HTTP 连接
            connection = (HttpURLConnection) new URL(HttpConstant.WebUrl.ROOT_PATH + url)
                    .openConnection();
            // 设置请求方法（GET、POST、等）
            connection.setRequestMethod(method);

            // 可选：设置请求头
            if (!headerMap.isEmpty()) {
                headerMap.forEach(connection::setRequestProperty);
            }

            processBefore(url, body, headerMap);

            // 获取输出流
            if (body != null && Objects.equals(method, HttpConstant.ReqMethod.POST)) {
                connection.setRequestProperty("Content-type", "application/json");
                connection.setDoOutput(true);
                wr = new DataOutputStream(connection.getOutputStream());
                wr.writeBytes((String) body);
                wr.flush();
            }

            if (Objects.equals(method, HttpConstant.ReqMethod.GET)){
                connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            }


            // 发送请求并获取响应码
            responseCode = connection.getResponseCode();

            // 读取响应数据
            BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String line;
            StringBuilder response = new StringBuilder();
            while ((line = reader.readLine()) != null) {
                response.append(line);
            }

            reader.close();
            processAfter(url, body, headerMap, response);

            return response.toString(); //怎么不封装成T ,泛型转化异常？？模块化结构的锅。

        } catch (IOException e) {
            processError(url, body, headerMap, responseCode, e.getMessage());
        } finally {
            if (null != connection) {
                connection.disconnect();
            }
            IoUtil.close(wr);
        }
        return null;
    }

    protected void processAfter(String url, Object body, Map<String, String> headerMap, StringBuilder response) {
        if (httpListenerList != null) {
            for (HttpListener httpListener : httpListenerList) {
                httpListener.processAfter(url, body, headerMap, response);
            }
        }
    }

    protected void processBefore(String url, Object body, Map<String, String> headerMap) {
        if (httpListenerList != null) {
            for (HttpListener httpListener : httpListenerList) {
                httpListener.processBefore(url, body, headerMap);
            }
        }
    }

    protected void processError(String url, Object body, Map<String, String> headerMap, int responseCode, String message) {
        if (httpListenerList != null) {
            for (HttpListener httpListener : httpListenerList) {
                httpListener.processError(url, body, headerMap, message, responseCode);
            }
        }
    }


    public Map<String, String> getHeaderMap() {
        return headerMap;
    }

    public void setHeaderMap(Map<String, String> headerMap) {
        this.headerMap = headerMap;
    }

    public List<HttpListener> getHttpListenerList() {
        return httpListenerList;
    }

    public void setHttpListenerList(List<HttpListener> httpListenerList) {
        this.httpListenerList = httpListenerList;
    }

}
